home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jed096_1.zip / SLANG / SRC / SLARRAY.C < prev    next >
C/C++ Source or Header  |  1994-04-26  |  13KB  |  588 lines

  1. /* Array manipulation routines for S-Lang */
  2. /* 
  3.  * Copyright (c) 1992, 1994 John E. Davis 
  4.  * All rights reserved.
  5.  *
  6.  * Permission is hereby granted, without written agreement and without
  7.  * license or royalty fees, to use, copy, and distribute this
  8.  * software and its documentation for any purpose, provided that the
  9.  * above copyright notice and the following two paragraphs appear in
  10.  * all copies of this software.
  11.  *
  12.  * IN NO EVENT SHALL JOHN E. DAVIS BE LIABLE TO ANY PARTY FOR DIRECT,
  13.  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
  14.  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOHN E. DAVIS
  15.  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * JOHN E. DAVIS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
  18.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  19.  * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
  20.  * BASIS, AND JOHN E. DAVIS HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
  21.  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  22.  */
  23.  
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "slang.h"
  28. #include "_slang.h"
  29. #include "slarray.h"
  30.  
  31. /* Array Stuff */
  32. #define MAX_ARRAYS 256
  33.  
  34. static SLArray_Type *Array_Table[MAX_ARRAYS];
  35.  
  36. static void free_array_handle (int hand)
  37. {
  38.    SLArray_Type *a = Array_Table[hand];
  39.    
  40.    if (a == NULL)
  41.      {
  42.     SLang_doerror ("Array is not allocated.");
  43.     return;
  44.      }
  45.  
  46.    if (a->flags) 
  47.      {
  48.     SLang_doerror ("Freeing an intrinsic array is illegal.");
  49.     return;
  50.      }
  51.    Array_Table[hand] = NULL;
  52.    FREE( a->ptr );
  53.    FREE(a);
  54. }
  55.  
  56. /* This routine may be called by application to free array handle created by 
  57.  * the application.  Returns 0 upon success, -1 if the handle is invalid and
  58.  * -2 if the handle is not associated with a C array.
  59.  */
  60. int SLang_free_array_handle (int hand)
  61. {
  62.    SLArray_Type *a = Array_Table[hand];
  63.    
  64.    if (a == NULL) return -1;
  65.    if (a->flags == 0) return -2;
  66.    Array_Table[hand] = NULL;
  67.    FREE(a);
  68.    return 0;
  69. }
  70.  
  71. static int alloc_array_handle (void)
  72. {
  73.    SLArray_Type **a, **amax;
  74.    a = Array_Table;
  75.    amax = a + MAX_ARRAYS;
  76.    while (a < amax)
  77.      {
  78.     if (*a == NULL) return ((int) (a - Array_Table));
  79.     a++;
  80.      }
  81.    SLang_doerror ("Array limit exceeded.");
  82.    return -1;
  83. }
  84.  
  85.     
  86. /* if ptr == NULL then malloc space.  Otherwise assume space is at ptr */
  87. int SLcreate_array(long *ptr, int dim, int d0, int d1, int d2,
  88.               unsigned char t, unsigned char flags)
  89. {
  90.    unsigned long n, size;
  91.    unsigned char type;
  92.    SLArray_Type *at;
  93.    int hand;
  94.  
  95.    
  96.    switch (t)
  97.      {
  98.       case 'i': type = INT_TYPE; size = sizeof(int); break;
  99.       case 's': type = STRING_TYPE; size = sizeof(char *); break;
  100.       case 'c': type = CHAR_TYPE; size = sizeof(char); break;
  101. #ifdef FLOAT_TYPE
  102.       case 'f': type = FLOAT_TYPE; size = sizeof(FLOAT); break;
  103. #endif
  104.       default: return (-1);
  105.      }
  106.  
  107.    /* This must be since indices go from 0 to d - 1 */
  108.    if (d1 < 1) d1 = 1;
  109.    if (d2 < 1) d2 = 1;
  110.    
  111.    n = d0;
  112.    n = n * d1;
  113.    n = n * d2;
  114.    
  115.    if (-1 == (hand = alloc_array_handle ())) return hand;
  116.  
  117.    if (NULL == (at = (SLArray_Type *) MALLOC(sizeof(SLArray_Type))))
  118.      {
  119.     return -1;
  120.      }
  121.  
  122.    if (ptr == NULL)
  123.      {
  124.     if (size == 1) ptr = (long *) MALLOC(n); else ptr = (long *) CALLOC(n, size);
  125.     if (ptr == NULL) return (-1);
  126.      }
  127.    
  128.    Array_Table [hand] = at;
  129.    
  130.    at->ptr = (long) ptr;
  131.    at->dim = dim;
  132.    at->x = d0; at->y = d1; at->z = d2;
  133.    at->type = type;
  134.    at->flags = flags;
  135.    return(hand);
  136. }
  137.  
  138. void SLpush_array (int at)
  139. {
  140.    SLang_Object_Type obj;
  141.    
  142.    obj.type = LANG_DATA | (ARRAY_TYPE << 8);
  143.    obj.v.i_val =  at;
  144.    SLang_push(&obj);
  145. }
  146.  
  147.  
  148. void SLang_create_array(void)
  149. {
  150.    int dim, d0, d1, d2, t;
  151.    int at;
  152.  
  153.    if (SLang_pop_integer(&dim)) return;
  154.  
  155.    if (dim > 3)
  156.      {
  157.     SLang_doerror("Array size not supported.");
  158.     return;
  159.      }
  160.  
  161.    d1 = d0 = d2 = 1;
  162.    switch(dim)
  163.      {
  164.       case 3: SLang_pop_integer(&d2);
  165.       case 2: SLang_pop_integer(&d1);
  166.       case 1: SLang_pop_integer(&d0);
  167.      }
  168.  
  169.    if (SLang_pop_integer(&t)) return;
  170.  
  171.    at = SLcreate_array(NULL, dim, d0, d1, d2, t, 0);
  172.    
  173.    if (at == -1)
  174.      {
  175.     SLang_doerror("Unable to create array.");
  176.     return;
  177.      }
  178.    
  179.    SLpush_array (at);
  180. }
  181.  
  182. void SLfree_array(void)
  183. {
  184.    SLang_Object_Type obj;
  185.    
  186.    if (SLang_pop(&obj)) return;
  187.  
  188.    if ((obj.type >> 8) != ARRAY_TYPE)
  189.      {
  190.     SLang_Error = TYPE_MISMATCH;
  191.     return;
  192.      }
  193.    
  194.    free_array_handle (obj.v.i_val);
  195. }
  196.  
  197. /* returns the array referenced by handle h */
  198. SLArray_Type *SLarray_from_handle (int h)
  199. {
  200.    return Array_Table[h];
  201. }
  202.  
  203.  
  204. /* returns array.  If *stype is non-zero, a string is accepted as an array.
  205.    If an actual array is popped, *stype will be zero upon return.  However,
  206.    if *stype is such that a string is permitted, *stype will be 1 if the
  207.    string that is returned (through the cast) should be freed.  */
  208.  
  209. SLArray_Type *SLang_pop_array(int *sflag)
  210. {
  211.    SLang_Object_Type obj;
  212.    unsigned short t;
  213.    
  214.    if (SLang_pop(&obj)) return(NULL);
  215.  
  216.    t = obj.type;
  217.    if ((t >> 8) != ARRAY_TYPE)
  218.      {
  219.     if ((*sflag == 0) || ((t >> 8) != STRING_TYPE))
  220.       {
  221.          SLang_Error = TYPE_MISMATCH;
  222.          return(NULL);
  223.       }
  224.     if ((t & 0xFF) == LANG_DATA) *sflag = 1; else *sflag = -1;
  225.     return (SLArray_Type *) obj.v.s_val;
  226.      }
  227.    *sflag = 0;
  228.    return SLarray_from_handle (obj.v.i_val);
  229. }
  230.  
  231. static char *Bound_err = "Array dims out of bounds";
  232. static unsigned int compute_array_offset(SLArray_Type *at)
  233. {
  234.    int elem[3], el, x[3], d, dim;
  235.    unsigned int off;
  236.  
  237.    if (SLang_Error) return(0);
  238.    dim = at->dim;
  239.    x[0] = at->x; x[1] = at->y; x[2] = at->z;
  240.    elem[0] = elem[1] = elem[2] = 0;
  241.    d = dim;
  242.  
  243.    while (d--)
  244.      {
  245.     if (SLang_pop_integer(&el)) return(0);
  246.     if ((el >= x[d]) || (el < 0))
  247.       {
  248.          SLang_doerror(Bound_err);
  249.          return(0);
  250.       }
  251.     elem[d] = el;
  252.      }
  253.  
  254.    off = 0;
  255.    d = 0;
  256. #if 0
  257.    while (d < dim)
  258.      {
  259.     off += off * x[d] + elem[d];
  260.     d++;
  261.      }
  262. #endif
  263.    off = (elem[0] * x[1] + elem[1]) * x[2] + elem[2];
  264.    
  265.    return(off);
  266. }
  267.  
  268.  
  269. static void str_get_elem(char *s, int dat)
  270. {
  271.    int n, nmax, ch;
  272.    if (SLang_pop_integer(&n)) goto done;
  273.    nmax = strlen(s);
  274.    if (nmax < n)
  275.      {
  276.     SLang_doerror(Bound_err);
  277.     goto done;
  278.      }
  279.    ch = s[n];
  280.    SLang_push_integer(ch);
  281.  
  282.    done:
  283.    if (dat == 1) FREE(s);
  284. }
  285.  
  286.    
  287.  
  288. void SLarray_putelem()
  289. {
  290.    SLArray_Type *at;
  291.    unsigned int off;
  292.    int sdat, i, *ip;
  293.    char *str, *newstr, **sp;
  294.    unsigned char *p, *ic;
  295. #ifdef FLOAT_TYPE
  296.    FLOAT f, *fp;
  297.    int ix;
  298.    int convert;
  299. #endif
  300.  
  301.    sdat = 0; if (NULL == (at = SLang_pop_array(&sdat))) return;
  302.  
  303.    if (at->flags == LANG_RVARIABLE)
  304.      {
  305.     SLang_Error = READONLY_ERROR;
  306.     return;
  307.      }
  308.    
  309.    off = compute_array_offset(at);
  310.    if (SLang_Error) return;
  311.  
  312.    p = (unsigned char *) at->ptr;
  313.    switch(at->type)
  314.      {
  315.     case INT_TYPE:
  316.       if (SLang_pop_integer(&i)) return;
  317.       ip = (int *) (off + (int *) p);
  318.       *ip = i; break;
  319.  
  320.     case STRING_TYPE:
  321.       if (SLang_pop_string(&str, &sdat)) return;
  322.       newstr = (char *) SLmake_string(str);
  323.       if (sdat == 1) FREE(str);
  324.       sp = (char **)(off + (char **) p);
  325.  
  326.       if (NULL != *sp) FREE(*sp);
  327.       *sp = newstr;
  328.       break;
  329.     
  330.       case CHAR_TYPE: 
  331.     if (SLang_pop_integer(&i)) return;
  332.     ic = (unsigned char *)(off + (unsigned char *) p);
  333.     *ic = (unsigned char) i;
  334.     break;
  335.  
  336. #ifdef FLOAT_TYPE
  337.       case FLOAT_TYPE: 
  338.     if (SLang_pop_float(&f, &convert, &ix)) return;
  339.     (void) convert;  (void) ix;
  340.     fp = off + (FLOAT *) p;
  341.     *fp = f;
  342.     break;
  343. #endif
  344.     default: SLang_doerror("Corrupted Array.");
  345.      }
  346.    return;
  347. }
  348.  
  349. static void array_push_element(SLArray_Type *at, int off)
  350. {
  351.    unsigned char *p;
  352.    p = (unsigned char *) at->ptr;
  353.    switch(at->type)
  354.      {
  355.       case INT_TYPE:  SLang_push_integer((int) *(((int *) p) + off)); break;
  356.       case CHAR_TYPE: SLang_push_integer((int) *(((unsigned char *) p) + off)); break;
  357.       case STRING_TYPE: 
  358.     if